#include "uart.h"

// 初始化串口
void Uart_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1时钟

    /* GPIO初始化 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    /* 配置Tx引脚为复用功能  */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_9;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* 连接 PXx 到 USARTx_Tx*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);

    USART_InitStructure.USART_BaudRate            = baudrate;                       // 设置波特率
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控制
    USART_InitStructure.USART_Mode                = USART_Mode_Tx;                  // 设置为发送模式
    USART_InitStructure.USART_Parity              = USART_Parity_No;                // 无校验位
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;               // 1位停止位
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;            // 8位数据位
    USART_Init(USART1, &USART_InitStructure);                                       // 初始化USART1

    USART_Cmd(USART1, ENABLE); // 使能USART1
}

// 发送一个字节
void Uart_SendByte(uint8_t byte)
{
    USART_SendData(USART1, byte);                                 // 发送数据
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完成
}

void Uart_SendArray(uint8_t *arr, uint16_t len)
{
    uint16_t i;
    for (i = 0; i < len; i++) // 遍历数组，逐个发送元素
    {
        Uart_SendByte(arr[i]); // 调用Uart_SendByte函数发送数组元素
    }
}

void Uart_SendString(char *str)
{
    uint8_t i;
    for (i = 0; str[i] != '\0'; i++) // 遍历字符串，直到遇到空字符'\0'
    {
        Uart_SendByte(str[i]); // 调用Uart_SendByte函数发送字符串中的字符
    }
}

static uint32_t Uart_Pow(uint32_t x, uint32_t y)
{
    uint32_t result = 1;
    while (y--) // 循环y次，计算x的y次方
    {
        result *= x; // 累乘结果
    }
    return result; // 返回结果
}

void Uart_SendNumber(uint32_t num, uint8_t len)
{
    uint8_t i;
    for (i = 0; i < len; i++) // 遍历数字的每一位
    {
        Uart_SendByte(num / Uart_Pow(10, len - i - 1) % 10 + '0'); // 将数字转换为字符并发送
    }
}

/// 重定向c库函数printf到串口，重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while ((USART1->SR & 0X40) == 0); // 等待上一次串口数据发送完成
    USART1->DR = (uint8_t)ch;         // 写DR,串口1将发送数据
    return ch;
}
